উন্নত ফিক্সচার কৌশলের মাধ্যমে Pytest-এর সম্পূর্ণ সম্ভাবনা উন্মোচন করুন। শক্তিশালী এবং কার্যকর পাইথন টেস্টিংয়ের জন্য প্যারামিটারাইজড টেস্টিং এবং মক ইন্টিগ্রেশনের ব্যবহার শিখুন।
Pytest অ্যাডভান্সড ফিক্সচারে দক্ষতা অর্জন: প্যারামিটারাইজড টেস্টিং এবং মক ইন্টিগ্রেশন
Pytest পাইথনের জন্য একটি শক্তিশালী এবং নমনীয় টেস্টিং ফ্রেমওয়ার্ক। এর সরলতা এবং প্রসারণযোগ্যতা এটিকে বিশ্বব্যাপী ডেভেলপারদের মধ্যে একটি প্রিয় করে তুলেছে। Pytest-এর অন্যতম আকর্ষণীয় বৈশিষ্ট্য হলো এর ফিক্সচার সিস্টেম, যা সুন্দর এবং পুনঃব্যবহারযোগ্য টেস্ট সেটআপের সুযোগ দেয়। এই ব্লগ পোস্টে আমরা উন্নত ফিক্সচার কৌশল, বিশেষ করে প্যারামিটারাইজড টেস্টিং এবং মক ইন্টিগ্রেশন-এর উপর আলোকপাত করব। আমরা দেখব কিভাবে এই কৌশলগুলি আপনার টেস্টিং ওয়ার্কফ্লোকে উল্লেখযোগ্যভাবে উন্নত করতে পারে, যা আরও শক্তিশালী এবং রক্ষণাবেক্ষণযোগ্য কোড তৈরিতে সাহায্য করে।
Pytest ফিক্সচার বোঝা
অ্যাডভান্সড টপিকে যাওয়ার আগে, আসুন সংক্ষেপে Pytest ফিক্সচারের মূল বিষয়গুলো পর্যালোচনা করি। একটি ফিক্সচার হলো একটি ফাংশন যা প্রতিটি টেস্ট ফাংশনের আগে চালানো হয় যেখানে এটি প্রয়োগ করা হয়। এটি টেস্টগুলোর জন্য একটি নির্দিষ্ট বেসলাইন প্রদান করতে ব্যবহৃত হয়, যা ধারাবাহিকতা নিশ্চিত করে এবং বয়লারপ্লেট কোড কমায়। ফিক্সচারগুলি নিম্নলিখিত কাজগুলি করতে পারে:
- একটি ডেটাবেস সংযোগ স্থাপন করা
- অস্থায়ী ফাইল বা ডিরেক্টরি তৈরি করা
- নির্দিষ্ট কনফিগারেশনসহ অবজেক্ট ইনিশিয়ালাইজ করা
- একটি API-এর সাথে প্রমাণীকরণ করা
ফিক্সচারগুলি কোডের পুনঃব্যবহারযোগ্যতা বাড়ায় এবং আপনার টেস্টগুলিকে আরও পঠনযোগ্য এবং রক্ষণাবেক্ষণযোগ্য করে তোলে। এদেরকে বিভিন্ন স্কোপে (ফাংশন, মডিউল, সেশন) সংজ্ঞায়িত করা যেতে পারে যাতে তাদের জীবনকাল এবং রিসোর্স ব্যবহার নিয়ন্ত্রণ করা যায়।
বেসিক ফিক্সচারের উদাহরণ
এখানে একটি Pytest ফিক্সচারের সহজ উদাহরণ দেওয়া হলো যা একটি অস্থায়ী ডিরেক্টরি তৈরি করে:
import pytest
import tempfile
import os
@pytest.fixture
def temp_dir():
with tempfile.TemporaryDirectory() as tmpdir:
yield tmpdir
এই ফিক্সচারটি একটি টেস্টে ব্যবহার করার জন্য, এটিকে আপনার টেস্ট ফাংশনের আর্গুমেন্ট হিসেবে অন্তর্ভুক্ত করুন:
def test_create_file(temp_dir):
filepath = os.path.join(temp_dir, "test_file.txt")
with open(filepath, "w") as f:
f.write("Hello, world!")
assert os.path.exists(filepath)
Pytest দিয়ে প্যারামিটারাইজড টেস্টিং
প্যারামিটারাইজড টেস্টিং আপনাকে একই টেস্ট ফাংশন বিভিন্ন ইনপুট ডেটা সেট দিয়ে একাধিকবার চালানোর সুযোগ দেয়। এটি বিশেষ করে বিভিন্ন ইনপুট এবং প্রত্যাশিত আউটপুটসহ ফাংশন পরীক্ষা করার জন্য খুবই উপকারী। Pytest প্যারামিটারাইজড টেস্ট বাস্তবায়নের জন্য @pytest.mark.parametrize ডেকোরেটর সরবরাহ করে।
প্যারামিটারাইজড টেস্টিংয়ের সুবিধা
- কোড ডুপ্লিকেশন হ্রাস: প্রায় একই রকম একাধিক টেস্ট ফাংশন লেখা এড়িয়ে চলুন।
- টেস্ট কভারেজ উন্নত করা: সহজেই বিস্তৃত পরিসরের ইনপুট মান পরীক্ষা করুন।
- টেস্টের পঠনযোগ্যতা বৃদ্ধি: প্রতিটি টেস্ট কেসের জন্য ইনপুট মান এবং প্রত্যাশিত আউটপুট স্পষ্টভাবে সংজ্ঞায়িত করুন।
বেসিক প্যারামিটারাইজেশন উদাহরণ
ধরা যাক, আপনার একটি ফাংশন আছে যা দুটি সংখ্যা যোগ করে:
def add(x, y):
return x + y
আপনি এই ফাংশনটি বিভিন্ন ইনপুট মান দিয়ে পরীক্ষা করার জন্য প্যারামিটারাইজড টেস্টিং ব্যবহার করতে পারেন:
import pytest
@pytest.mark.parametrize("x, y, expected", [
(1, 2, 3),
(5, 5, 10),
(-1, 1, 0),
(0, 0, 0),
])
def test_add(x, y, expected):
assert add(x, y) == expected
এই উদাহরণে, @pytest.mark.parametrize ডেকোরেটরটি চারটি টেস্ট কেস সংজ্ঞায়িত করে, প্রতিটিতে x, y, এবং প্রত্যাশিত ফলাফলের জন্য ভিন্ন ভিন্ন মান রয়েছে। Pytest test_add ফাংশনটি চারবার চালাবে, প্রতিটি প্যারামিটার সেটের জন্য একবার করে।
অ্যাডভান্সড প্যারামিটারাইজেশন কৌশল
Pytest প্যারামিটারাইজেশনের জন্য বেশ কিছু উন্নত কৌশল সরবরাহ করে, যার মধ্যে রয়েছে:
- প্যারামিটারাইজেশনের সাথে ফিক্সচার ব্যবহার: প্রতিটি টেস্ট কেসের জন্য বিভিন্ন সেটআপ সরবরাহ করতে ফিক্সচারকে প্যারামিটারাইজেশনের সাথে একত্রিত করুন।
- টেস্ট কেসের জন্য আইডি: উন্নত রিপোর্টিং এবং ডিবাগিংয়ের জন্য টেস্ট কেসগুলিতে কাস্টম আইডি বরাদ্দ করুন।
- ইনডাইরেক্ট প্যারামিটারাইজেশন: ফিক্সচারে পাঠানো আর্গুমেন্টগুলিকে প্যারামিটারাইজ করুন, যা ডাইনামিক ফিক্সচার তৈরির সুযোগ দেয়।
প্যারামিটারাইজেশনের সাথে ফিক্সচার ব্যবহার
এটি আপনাকে টেস্টে পাঠানো প্যারামিটারের উপর ভিত্তি করে ডাইনামিকভাবে ফিক্সচার কনফিগার করার সুযোগ দেয়। কল্পনা করুন আপনি একটি ফাংশন পরীক্ষা করছেন যা একটি ডেটাবেসের সাথে ইন্টারঅ্যাক্ট করে। আপনি বিভিন্ন টেস্ট কেসের জন্য বিভিন্ন ডেটাবেস কনফিগারেশন (যেমন, ভিন্ন সংযোগ স্ট্রিং) ব্যবহার করতে চাইতে পারেন।
import pytest
@pytest.fixture
def db_config(request):
if request.param == "prod":
return {"host": "prod.example.com", "port": 5432}
elif request.param == "test":
return {"host": "test.example.com", "port": 5433}
else:
raise ValueError("Invalid database environment")
@pytest.fixture
def db_connection(db_config):
# Simulate establishing a database connection
print(f"Connecting to database at {db_config['host']}:{db_config['port']}")
return f"Connection to {db_config['host']}"
@pytest.mark.parametrize("db_config", ["prod", "test"], indirect=True)
def test_database_interaction(db_connection):
# Your test logic here, using the db_connection fixture
print(f"Using connection: {db_connection}")
assert "Connection" in db_connection
এই উদাহরণে, db_config ফিক্সচারটি প্যারামিটারাইজড। indirect=True আর্গুমেন্টটি Pytest-কে প্যারামিটারগুলি ("prod" এবং "test") db_config ফিক্সচার ফাংশনে পাঠাতে বলে। এরপর db_config ফিক্সচার প্যারামিটারের মানের উপর ভিত্তি করে বিভিন্ন ডেটাবেস কনফিগারেশন রিটার্ন করে। db_connection ফিক্সচারটি ডেটাবেস সংযোগ স্থাপনের জন্য db_config ফিক্সচার ব্যবহার করে। অবশেষে, test_database_interaction ফাংশনটি ডেটাবেসের সাথে ইন্টারঅ্যাক্ট করার জন্য db_connection ফিক্সচার ব্যবহার করে।
টেস্ট কেসের জন্য আইডি
কাস্টম আইডি আপনার টেস্ট রিপোর্টে টেস্ট কেসগুলির জন্য আরও বর্ণনামূলক নাম সরবরাহ করে, যা ব্যর্থতা সনাক্ত করা এবং ডিবাগ করা সহজ করে তোলে।
import pytest
@pytest.mark.parametrize(
"input_string, expected_output",
[
("hello", "HELLO"),
("world", "WORLD"),
("", ""),
],
ids=["lowercase_hello", "lowercase_world", "empty_string"],
)
def test_uppercase(input_string, expected_output):
assert input_string.upper() == expected_output
আইডি ছাড়া, Pytest test_uppercase[0], test_uppercase[1] ইত্যাদির মতো জেনেরিক নাম তৈরি করত। আইডি ব্যবহার করলে, টেস্ট রিপোর্টে test_uppercase[lowercase_hello]-এর মতো আরও অর্থবহ নাম প্রদর্শিত হবে।
ইনডাইরেক্ট প্যারামিটারাইজেশন
ইনডাইরেক্ট প্যারামিটারাইজেশন আপনাকে সরাসরি টেস্ট ফাংশনের পরিবর্তে একটি ফিক্সচারের ইনপুটকে প্যারামিটারাইজ করতে দেয়। এটি যখন আপনি প্যারামিটার মানের উপর ভিত্তি করে বিভিন্ন ফিক্সচার ইনস্ট্যান্স তৈরি করতে চান তখন সহায়ক।
import pytest
@pytest.fixture
def input_data(request):
if request.param == "valid":
return {"name": "John Doe", "email": "john.doe@example.com"}
elif request.param == "invalid":
return {"name": "", "email": "invalid-email"}
else:
raise ValueError("Invalid input data type")
def validate_data(data):
if not data["name"]:
return False, "Name cannot be empty"
if "@" not in data["email"]:
return False, "Invalid email address"
return True, "Valid data"
@pytest.mark.parametrize("input_data", ["valid", "invalid"], indirect=True)
def test_validate_data(input_data):
is_valid, message = validate_data(input_data)
if input_data == {"name": "John Doe", "email": "john.doe@example.com"}:
assert is_valid is True
assert message == "Valid data"
else:
assert is_valid is False
assert message in ["Name cannot be empty", "Invalid email address"]
এই উদাহরণে, input_data ফিক্সচারটি "valid" এবং "invalid" মান দিয়ে প্যারামিটারাইজ করা হয়েছে। indirect=True আর্গুমেন্টটি Pytest-কে এই মানগুলি input_data ফিক্সচার ফাংশনে পাঠাতে বলে। এরপর input_data ফিক্সচারটি প্যারামিটার মানের উপর ভিত্তি করে বিভিন্ন ডেটা ডিকশনারি রিটার্ন করে। test_validate_data ফাংশনটি এরপর বিভিন্ন ইনপুট ডেটা দিয়ে validate_data ফাংশন পরীক্ষা করার জন্য input_data ফিক্সচার ব্যবহার করে।
Pytest-এর সাথে মকিং
মকিং হলো একটি কৌশল যা টেস্টিংয়ের সময় আসল ডিপেন্ডেন্সিগুলিকে নিয়ন্ত্রিত বিকল্প (মক) দিয়ে প্রতিস্থাপন করতে ব্যবহৃত হয়। এটি আপনাকে পরীক্ষাধীন কোডকে বিচ্ছিন্ন করতে এবং ডেটাবেস, এপিআই বা ফাইল সিস্টেমের মতো বাহ্যিক সিস্টেমের উপর নির্ভরতা এড়াতে দেয়।
মকিংয়ের সুবিধা
- কোড বিচ্ছিন্ন করা: বাহ্যিক ডিপেন্ডেন্সির উপর নির্ভর না করে কোডকে বিচ্ছিন্নভাবে পরীক্ষা করুন।
- আচরণ নিয়ন্ত্রণ: রিটার্ন ভ্যালু এবং ব্যতিক্রমের মতো ডিপেন্ডেন্সিগুলির আচরণ নির্ধারণ করুন।
- টেস্ট দ্রুত করা: ধীর বা অবিশ্বস্ত বাহ্যিক সিস্টেম এড়িয়ে চলুন।
- এজ কেস পরীক্ষা করা: ত্রুটির পরিস্থিতি এবং এজ কেসগুলি সিমুলেট করুন যা বাস্তব পরিবেশে পুনরুৎপাদন করা কঠিন।
unittest.mock লাইব্রেরি ব্যবহার করা
পাইথন মক তৈরির জন্য unittest.mock লাইব্রেরি সরবরাহ করে। Pytest unittest.mock-এর সাথে নির্বিঘ্নে একীভূত হয়, যা আপনার টেস্টগুলিতে ডিপেন্ডেন্সি মক করা সহজ করে তোলে।
বেসিক মকিং উদাহরণ
ধরা যাক আপনার একটি ফাংশন আছে যা একটি বাহ্যিক API থেকে ডেটা নিয়ে আসে:
import requests
def get_data_from_api(url):
response = requests.get(url)
response.raise_for_status() # Raise an exception for bad status codes
return response.json()
API-তে প্রকৃত অনুরোধ না করে এই ফাংশনটি পরীক্ষা করার জন্য, আপনি requests.get ফাংশনটি মক করতে পারেন:
import pytest
import requests
from unittest.mock import patch
@patch("requests.get")
def test_get_data_from_api(mock_get):
# Configure the mock to return a specific response
mock_get.return_value.json.return_value = {"data": "test data"}
mock_get.return_value.status_code = 200
# Call the function being tested
data = get_data_from_api("https://example.com/api")
# Assert that the mock was called with the correct URL
mock_get.assert_called_once_with("https://example.com/api")
# Assert that the function returned the expected data
assert data == {"data": "test data"}
এই উদাহরণে, @patch("requests.get") ডেকোরেটরটি requests.get ফাংশনটিকে একটি মক অবজেক্ট দিয়ে প্রতিস্থাপন করে। mock_get আর্গুমেন্টটি হলো মক অবজেক্ট। আমরা তখন মক অবজেক্টটিকে একটি নির্দিষ্ট প্রতিক্রিয়া রিটার্ন করার জন্য কনফিগার করতে পারি এবং এটি সঠিক URL দিয়ে কল করা হয়েছিল কিনা তা যাচাই করতে পারি।
ফিক্সচারের সাথে মকিং
আপনি মক তৈরি এবং পরিচালনা করতে ফিক্সচারও ব্যবহার করতে পারেন। এটি একাধিক টেস্ট জুড়ে মক শেয়ার করার জন্য বা আরও জটিল মক সেটআপ তৈরির জন্য উপকারী হতে পারে।
import pytest
import requests
from unittest.mock import Mock
@pytest.fixture
def mock_api_get():
mock = Mock()
mock.return_value.json.return_value = {"data": "test data"}
mock.return_value.status_code = 200
return mock
@pytest.fixture
def patched_get(mock_api_get, monkeypatch):
monkeypatch.setattr(requests, "get", mock_api_get)
return mock_api_get
def test_get_data_from_api(patched_get):
# Call the function being tested
data = get_data_from_api("https://example.com/api")
# Assert that the mock was called with the correct URL
patched_get.assert_called_once_with("https://example.com/api")
# Assert that the function returned the expected data
assert data == {"data": "test data"}
এখানে, mock_api_get একটি মক তৈরি করে এবং তা রিটার্ন করে। patched_get তারপর monkeypatch ব্যবহার করে, যা একটি pytest ফিক্সচার, আসল `requests.get`-কে মক দিয়ে প্রতিস্থাপন করে। এটি অন্যান্য টেস্টগুলিকে একই মক করা API এন্ডপয়েন্ট ব্যবহার করার সুযোগ দেয়।
অ্যাডভান্সড মকিং কৌশল
Pytest এবং unittest.mock বেশ কিছু উন্নত মকিং কৌশল সরবরাহ করে, যার মধ্যে রয়েছে:
- সাইড এফেক্টস: ইনপুট আর্গুমেন্টের উপর ভিত্তি করে মকের জন্য কাস্টম আচরণ নির্ধারণ করুন।
- প্রপার্টি মকিং: অবজেক্টের প্রপার্টি মক করুন।
- কনটেক্সট ম্যানেজার: অস্থায়ী প্রতিস্থাপনের জন্য কনটেক্সট ম্যানেজারের মধ্যে মক ব্যবহার করুন।
সাইড এফেক্টস
সাইড এফেক্টস আপনাকে ইনপুট আর্গুমেন্টের উপর ভিত্তি করে আপনার মকের জন্য কাস্টম আচরণ নির্ধারণ করতে দেয়। এটি বিভিন্ন পরিস্থিতি বা ত্রুটির অবস্থা সিমুলেট করার জন্য উপকারী।
import pytest
from unittest.mock import Mock
def test_side_effect():
mock = Mock()
mock.side_effect = [1, 2, 3]
assert mock() == 1
assert mock() == 2
assert mock() == 3
with pytest.raises(StopIteration):
mock()
এই মকটি ক্রমাগত কলে 1, 2, এবং 3 রিটার্ন করে, তারপর তালিকা শেষ হয়ে গেলে একটি `StopIteration` ব্যতিক্রম উত্থাপন করে।
প্রপার্টি মকিং
প্রপার্টি মকিং আপনাকে অবজেক্টের উপর প্রপার্টির আচরণ মক করতে দেয়। এটি মেথডের পরিবর্তে অবজেক্ট প্রপার্টির উপর নির্ভরশীল কোড পরীক্ষা করার জন্য উপকারী।
import pytest
from unittest.mock import patch
class MyClass:
@property
def my_property(self):
return "original value"
def test_property_mocking():
obj = MyClass()
with patch.object(obj, "my_property", new_callable=pytest.PropertyMock) as mock_property:
mock_property.return_value = "mocked value"
assert obj.my_property == "mocked value"
এই উদাহরণটি MyClass অবজেক্টের my_property প্রপার্টিকে মক করে, যা আপনাকে পরীক্ষার সময় এর রিটার্ন মান নিয়ন্ত্রণ করতে দেয়।
কনটেক্সট ম্যানেজার
কনটেক্সট ম্যানেজারের মধ্যে মক ব্যবহার করলে আপনি কোডের একটি নির্দিষ্ট ব্লকের জন্য সাময়িকভাবে ডিপেন্ডেন্সি প্রতিস্থাপন করতে পারেন। এটি বাহ্যিক সিস্টেম বা রিসোর্সের সাথে ইন্টারঅ্যাক্ট করে এমন কোড পরীক্ষা করার জন্য উপকারী যা শুধুমাত্র সীমিত সময়ের জন্য মক করা উচিত।
import pytest
from unittest.mock import patch
def test_context_manager_mocking():
with patch("os.path.exists") as mock_exists:
mock_exists.return_value = True
assert os.path.exists("dummy_path") is True
# The mock is automatically reverted after the 'with' block
# Ensure the original function is restored, although we can't really assert
# the real `os.path.exists` function's behavior without a real path.
# The important thing is that the patch is gone after the context.
print("Mock has been removed")
প্যারামিটারাইজেশন এবং মকিং একত্রিত করা
এই দুটি শক্তিশালী কৌশলকে আরও পরিশীলিত এবং কার্যকর টেস্ট তৈরি করতে একত্রিত করা যেতে পারে। আপনি বিভিন্ন মক কনফিগারেশনের সাথে বিভিন্ন পরিস্থিতি পরীক্ষা করার জন্য প্যারামিটারাইজেশন ব্যবহার করতে পারেন।
import pytest
import requests
from unittest.mock import patch
def get_user_data(user_id):
url = f"https://api.example.com/users/{user_id}"
response = requests.get(url)
response.raise_for_status()
return response.json()
@pytest.mark.parametrize(
"user_id, expected_data",
[
(1, {"id": 1, "name": "John Doe"}),
(2, {"id": 2, "name": "Jane Smith"}),
],
)
@patch("requests.get")
def test_get_user_data(mock_get, user_id, expected_data):
mock_get.return_value.json.return_value = expected_data
mock_get.return_value.status_code = 200
data = get_user_data(user_id)
assert data == expected_data
mock_get.assert_called_once_with(f"https://api.example.com/users/{user_id}")
এই উদাহরণে, test_get_user_data ফাংশনটি বিভিন্ন user_id এবং expected_data মান দিয়ে প্যারামিটারাইজ করা হয়েছে। @patch ডেকোরেটর requests.get ফাংশনটিকে মক করে। Pytest টেস্ট ফাংশনটি দুবার চালাবে, প্রতিটি প্যারামিটার সেটের জন্য একবার করে, যেখানে মকটি সংশ্লিষ্ট expected_data রিটার্ন করার জন্য কনফিগার করা হয়েছে।
অ্যাডভান্সড ফিক্সচার ব্যবহারের সেরা অনুশীলন
- ফিক্সচার ফোকাসড রাখুন: প্রতিটি ফিক্সচারের একটি স্পষ্ট এবং নির্দিষ্ট উদ্দেশ্য থাকা উচিত।
- উপযুক্ত স্কোপ ব্যবহার করুন: রিসোর্সের ব্যবহার অপ্টিমাইজ করার জন্য উপযুক্ত ফিক্সচার স্কোপ (ফাংশন, মডিউল, সেশন) বেছে নিন।
- ফিক্সচার ডকুমেন্ট করুন: প্রতিটি ফিক্সচারের উদ্দেশ্য এবং ব্যবহার স্পষ্টভাবে ডকুমেন্ট করুন।
- অতিরিক্ত মকিং এড়িয়ে চলুন: শুধুমাত্র সেইসব ডিপেন্ডেন্সি মক করুন যা পরীক্ষাধীন কোডকে বিচ্ছিন্ন করার জন্য প্রয়োজনীয়।
- স্পষ্ট অ্যাসারশন লিখুন: নিশ্চিত করুন যে আপনার অ্যাসারশনগুলি স্পষ্ট এবং নির্দিষ্ট, যা পরীক্ষাধীন কোডের প্রত্যাশিত আচরণ যাচাই করে।
- টেস্ট-ড্রিভেন ডেভেলপমেন্ট (TDD) বিবেচনা করুন: কোড লেখার আগে আপনার টেস্ট লিখুন, উন্নয়ন প্রক্রিয়াকে গাইড করার জন্য ফিক্সচার এবং মক ব্যবহার করুন।
উপসংহার
Pytest-এর উন্নত ফিক্সচার কৌশল, যার মধ্যে প্যারামিটারাইজড টেস্টিং এবং মক ইন্টিগ্রেশন অন্তর্ভুক্ত, শক্তিশালী, কার্যকর এবং রক্ষণাবেক্ষণযোগ্য টেস্ট লেখার জন্য শক্তিশালী টুল সরবরাহ করে। এই কৌশলগুলিতে দক্ষতা অর্জনের মাধ্যমে, আপনি আপনার পাইথন কোডের গুণমান উল্লেখযোগ্যভাবে উন্নত করতে পারেন এবং আপনার টেস্টিং ওয়ার্কফ্লোকে সহজতর করতে পারেন। স্পষ্ট, ফোকাসড ফিক্সচার তৈরি করা, উপযুক্ত স্কোপ ব্যবহার করা এবং ব্যাপক অ্যাসারশন লেখার উপর মনোযোগ দিতে মনে রাখবেন। অনুশীলনের মাধ্যমে, আপনি একটি ব্যাপক এবং কার্যকর টেস্টিং কৌশল তৈরি করতে Pytest-এর ফিক্সচার সিস্টেমের সম্পূর্ণ সম্ভাবনাকে কাজে লাগাতে সক্ষম হবেন।